package com.wedo.commons.utils;

import com.alibaba.fastjson.JSONObject;
import com.wedo.commons.exception.BaseException;
import com.wedo.commons.exception.ExceptionCode;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.zip.GZIPInputStream;

/**
 * Created by mofei_000 on 2016/11/24.
 */
public class HttpUtils {
    public final static String CONNECTION_TIMEOUT = "CONNECTION_TIMEOUT";// 从角色
    private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);

    /**
     * 根据url取得数据，支持gzip类网站
     *
     * @param url
     * @param charset
     * @return
     * @throws ParseException
     * @throws IOException
     */
    public static String getContentByUrl(String url, String charset,boolean isTimeOut,int timeOut,Map<String,String> header) throws BaseException {
        HttpClient httpclient = new DefaultHttpClient();
        if (isTimeOut) {
            httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeOut);
        }
        HttpGet httpget = new HttpGet(url);
        if(header!=null){
            Iterator<String> iterator=header.keySet().iterator();
            while(iterator.hasNext()){
                String key= iterator.next();
                String value=header.get(key);
                httpget.setHeader(key,value);
            }
        }
        HttpResponse response = null;
        try {
            response = httpclient.execute(httpget);
        } catch (IOException e) {
            httpget.abort();
            throw new BaseException(ExceptionCode.HTTP_UNREACHED,e.getMessage());
        }
        if (StringUtils.isEmpty(charset)) {
            String defaultCharset = "iso-8859-1";
            Header contentTypeHeader = response.getFirstHeader("Content-Type");
            String contentType = contentTypeHeader.getValue().toLowerCase();
            if (contentType.indexOf("gbk") > -1 || contentType.indexOf("gb2312") > -1 || contentType.indexOf("gb18030") > -1) {
                defaultCharset = "gb18030";
            } else if (contentType.indexOf("utf-8") > -1) {
                defaultCharset = "utf-8";
            } else if (contentType.indexOf("big5") > -1) {
                defaultCharset = "big5";
            }
            charset = defaultCharset;
        }
        Header contentEncoding = response.getFirstHeader("Content-Encoding");
        StatusLine line = response.getStatusLine();
        if (line.getStatusCode() == 200) {
            InputStream is=null;
            try{
                HttpEntity entity = response.getEntity();

                if (contentEncoding != null && contentEncoding.getValue().toLowerCase().equals("gzip")) {
                    is = new GZIPInputStream(entity.getContent());
                } else {
                    is = entity.getContent();
                }
                String str = inputStream2String(is, charset);

                return str;
            }catch (IOException e){
                throw new BaseException(ExceptionCode.HTTP_SELFEXCEPTION,e.getMessage());
            }finally{
                if(is!=null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        throw new BaseException(ExceptionCode.HTTP_SELFEXCEPTION,e.getMessage());
                    }
                }
            }
        }else{
            BaseException exception=null;
            String httpStatusCode=String.valueOf(line.getStatusCode());
            if(StringUtils.isNotBlank(httpStatusCode)){
                if(httpStatusCode.startsWith("4")){
                    exception=new BaseException(ExceptionCode.HTTP_UNREACHED,"404");
                }else if(httpStatusCode.startsWith("5")){
                    exception=new BaseException(ExceptionCode.HTTP_UNREACHED,"500");
                }else{
                    exception=new BaseException(ExceptionCode.HTTP_UNREACHED,"timeout");
                }
            }
            if(exception!=null){
                throw exception;
            }
        }
        return "";
    }
    /**
     * 根据url取得数据，支持gzip类网站
     *
     * @param url
     * @param param
     * @return
     * @throws ParseException
     * @throws IOException
     */
    public static String getBlockIdByUrl(String url, String param) throws BaseException {
        HttpClient httpclient = new DefaultHttpClient();

        HttpGet httpget = new HttpGet(url);
        HttpResponse response = null;
        try {
            response = httpclient.execute(httpget);
        } catch (IOException e) {
            throw new BaseException(ExceptionCode.HTTP_UNREACHED,"");
        }
        String defaultCharset = "iso-8859-1";
        Header contentTypeHeader = response.getFirstHeader("X-CustomEvent-$class");
        String contentType = contentTypeHeader.getValue();

        StatusLine line = response.getStatusLine();
        if (line.getStatusCode() == 200) {
            JSONObject obj = (JSONObject)JSONObject.parse(contentType) ;
            return obj.getString(param) ;
        }
        throw new BaseException(ExceptionCode.HTTP_SELFEXCEPTION,"");
    }


    public static String getContentByUrl(String url,Map<String,String> headers,boolean isTimeOut,int timeout) throws BaseException {
        try {
            return getContentByUrl(url, "",isTimeOut,timeout,headers);
        } catch (BaseException e) {
            throw e;
        }
    }

    public static String post(String url, String requestBody) throws BaseException {
        return post(url, requestBody, true, 1000*10);
    }

    public static String post(String url, String requestBody,Map<String,String> headers, Boolean isTimeOut, Integer timeOut) throws BaseException {
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httpost = new HttpPost(url);
        if(headers!=null){
            Iterator<String> iterator=headers.keySet().iterator();
            while(iterator.hasNext()){
                String key=iterator.next();
                httpost.addHeader(key, headers.get(key));
            }
        }
//		System.out.println(requestBody);
        if (isTimeOut) {
            httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeOut);
        }
        StringEntity reqEntity = null;
        /*try {*/
            reqEntity = new StringEntity(requestBody, HTTP.UTF_8);
        /*} catch (UnsupportedEncodingException e) {
            throw new BaseException(ExceptionCode.HTTP_UNREACHED,"");
        }*/
        //reqEntity.setContentEncoding(HTTP.UTF_8);
        reqEntity.setContentType("application/json; charset=UTF-8");
        httpost.setEntity(reqEntity);

        // System.out.println(reqEntity.getContent().);
        //执行推送请求
        String body = null;
        try {
            body = invoke(httpclient, httpost);
        } catch (IOException e) {
            throw new BaseException(ExceptionCode.HTTP_UNREACHED,"");
        }finally {
            httpclient.getConnectionManager().shutdown();
        }
        return body;
    }

    public static String post(String url, String requestBody, Boolean isTimeOut, Integer timeOut) throws BaseException {
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httpost = new HttpPost(url);

//		httpost.addHeader("Content-Type", "application/json; charset=UTF-8");
//		System.out.println(requestBody);
        if (isTimeOut) {
            httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeOut);
        }
        try {
            StringEntity reqEntity = null;
//            try {
                reqEntity = new StringEntity(requestBody, HTTP.UTF_8);
//            } catch (UnsupportedEncodingException e) {
//                throw new BaseException(ExceptionCode.HTTP_UNREACHED,e.getMessage());
//            }
            //reqEntity.setContentEncoding(HTTP.UTF_8);
            reqEntity.setContentType("application/json; charset=UTF-8");
            httpost.setEntity(reqEntity);

            // System.out.println(reqEntity.getContent().);
            //执行推送请求
            String body = null;
            try {
                body = invoke(httpclient, httpost);
            } catch (IOException e) {
                throw new BaseException(ExceptionCode.HTTP_UNREACHED,e.getMessage());
            }
            return body;
        } finally {
            httpclient.getConnectionManager().shutdown();
        }
    }

    public static byte[] post(String url,byte[] bytes,Integer timeOut) throws BaseException {
        HttpClient httpclient = new DefaultHttpClient();

//		httpost.addHeader("Content-Type", "application/json; charset=UTF-8");
//		System.out.println(requestBody);
        httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeOut);
        httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,1000*8);
        try {
            HttpPost post= null;
            post = postBytes(url,bytes);
            //执行推送请求
            return invokeBytes(httpclient, post);
        }catch (UnsupportedEncodingException e) {
            throw new BaseException(ExceptionCode.HTTP_UNREACHED,e.getMessage());
        }catch (BaseException e) {
            throw e;
        } finally {
            httpclient.getConnectionManager().shutdown();
        }
    }

    @SuppressWarnings("deprecation")
    public static String post(String url, Map<String, Object> params) throws ClientProtocolException, IOException {
        HttpClient httpclient = new DefaultHttpClient();
        String body = null;
        httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 60000);
        try {
            HttpPost post = postForm(url, params);
            body = invoke(httpclient, post);
            return body;
        } finally {
            httpclient.getConnectionManager().shutdown();
        }

    }

    /**
     * 支持gzip
     * @param httpclient
     * @param httpost
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    private static String invoke(HttpClient httpclient, HttpUriRequest httpost) throws ClientProtocolException, IOException {
        // modify by qiong.wang 2014/06/24
        // add header for sns security check when invoke sns api service.
        HttpResponse response = httpclient.execute(httpost);
        HttpEntity entity = response.getEntity();
        //mofei
        Header[] encodings=response.getHeaders("Content-Encoding");
        boolean supportGzip=false;
        if(encodings!=null&&encodings.length>0){
            for (Header encoding : encodings) {
                if("gzip".equals(encoding.getValue())){
                    supportGzip=true;
                    break;
                }
            }
        }
        if (supportGzip){
            String defaultCharset = "utf-8";
            Header contentTypeHeader = response.getFirstHeader("Content-Type");
            String contentType = contentTypeHeader.getValue().toLowerCase();
            if (contentType.indexOf("gbk") > -1 || contentType.indexOf("gb2312") > -1 || contentType.indexOf("gb18030") > -1) {
                defaultCharset = "gb18030";
            } else if (contentType.indexOf("utf-8") > -1) {
                defaultCharset = "utf-8";
            } else if (contentType.indexOf("big5") > -1) {
                defaultCharset = "big5";
            }
            InputStream is = new GZIPInputStream(entity.getContent());
            return inputStream2String(is,defaultCharset);
        }
        String body=null;
        if(entity!=null){
            body= EntityUtils.toString(entity);
        }
        return body;
    }

    private static byte[] invokeBytes(HttpClient httpclient, HttpUriRequest httpost) throws BaseException {
        // modify by qiong.wang 2014/06/24
        // add header for sns security check when invoke sns api service.
        HttpResponse response = null;
        try {
            response = httpclient.execute(httpost);
        } catch (IOException e) {
            throw new BaseException(ExceptionCode.HTTP_UNREACHED,e.getMessage());
        }

        HttpEntity entity = response.getEntity();

        //String body = EntityUtils.toString(entity);

        if(entity == null) {
            return null ;
        }
        try {
            return EntityUtils.toByteArray(entity);
        } catch (IOException e) {
            throw new BaseException(ExceptionCode.HTTP_SELFEXCEPTION,e.getMessage());
        }
    }

    private static HttpPost postForm(String url, Map<String, Object> params) throws UnsupportedEncodingException {
        HttpPost httpost = new HttpPost(url);
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        Set<String> keySet = params.keySet();


        for (String key : keySet) {
            Object v= params.get(key);
            if (v instanceof List){
                List list=(List)v;
                for (int i = 0; i < list.size(); i++) {
                    nvps.add(new BasicNameValuePair(key,(String) list.get(i) ));
                }
            }else{
                nvps.add(new BasicNameValuePair(key,(String)v));
            }

        }
        httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));

        return httpost;
    }

    private static HttpPost postBytes(String url,byte[] bytes) throws UnsupportedEncodingException {
        HttpPost post=new HttpPost(url);
        HttpEntity entity=new ByteArrayEntity(bytes);
        post.setEntity(entity);
        return post;
    }

    public static String inputStream2String(InputStream input, String charset)
            throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(input,
                charset));
        StringBuffer buffer = new StringBuffer();
        String line = "";
        while ((line = in.readLine()) != null) {
            buffer.append(line + "\n");
        }
        return buffer.toString();
    }

    public static int getResponseCode(String urlString) throws MalformedURLException, IOException {
        URL u = new URL(urlString);
        HttpURLConnection huc = (HttpURLConnection) u.openConnection();
        huc.setRequestMethod("GET");
        huc.connect();
        return huc.getResponseCode();
    }

    /***
     *取出HttpServletRequest 中的请求体
     */
    public static String getRequestBody(HttpServletRequest request){
        BufferedReader br=null;
        String wholeStr="";
        try {
            br = request.getReader();
            String str = "";
            while((str = br.readLine()) != null){
                wholeStr += str;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return  wholeStr;
    }
    public static void main(String[] args) throws BaseException {
        String keys= HttpUtils.post("http://lotto.sina.cn/ai","");
        System.out.println(keys);
    }
}
